package com.zj.study;

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;

public class 基本计算器2加减含括号 {

    public static void main(String[] args) {
//        String aa="1+(2-(3 + 4))-(7+1)+((2+3)+1)";
//        String aa="(1)";
//        String aa="-2 +1";
//        String aa="1-(10-2+3)";
        String aa = "(1+(4+5+2)-3)+(6+8)";

        System.out.println(calculate(aa));
    }

    public static Integer calculate(String s) {
        int res = 0;
        Integer num = 0;
        Deque<Integer> optQue1 = new ArrayDeque<>();
        optQue1.push(1);
        int sign = 1;
        for (int i = 0; i < s.length(); i++) {
            if (Character.isDigit(s.charAt(i))) {//采用即时算的方式时就要取完一个数时就要计算
                num = s.charAt(i) - '0' + num * 10;
                if (i == s.length() - 1 || (i < s.length() - 1 && !Character.isDigit(s.charAt(i + 1)))) {
                    res += sign * num;
                }
            } else if (s.charAt(i) == '(') {
                optQue1.push(sign);
            } else if (s.charAt(i) == ')') {
                optQue1.pop();
            } else if (s.charAt(i) == '-') {
                sign = -optQue1.peek();
            } else if (s.charAt(i) == '+') {
                sign = optQue1.peek();
            }
        }
        return res;
    }

    public static Integer calculate3(String s) {
        Deque<Character> optQue1 = new ArrayDeque<>();
        Deque<Integer> numeQue = new ArrayDeque<>();
        int res = 0;
        Integer num = 0;//只有当当前字符为符号时，才能确定上一个完整的数，同时解决了负号开头的问题。延时取数的方式适用于有一个队列存放了数，最后一起算的情况。
        for (int i = 0; i < s.length(); i++) {
            if (Character.isDigit(s.charAt(i))) {
                num = s.charAt(i) - '0' + num * 10;
            } else if (s.charAt(i) == '(') {
                optQue1.push(s.charAt(i));
            } else if (s.charAt(i) == ')') {
                num = getInteger(optQue1, numeQue, num);//关键判断，此处不要把结果放入队列
                optQue1.pop();
            }
            if (s.charAt(i) == '+' || s.charAt(i) == '-' || i == s.length() - 1) {
                num = getInteger(optQue1, numeQue, num);//关键步骤，有平级的运算先算完。
                if (i != s.length() - 1) {
                    optQue1.push(s.charAt(i));
                    numeQue.push(num);//关键判断，此处要把结果放入队列，但最后一个不放入队列。
                    num = 0;
                }
            }
        }
        return num;
    }

    private static Integer getInteger(Deque<Character> optQue1, Deque<Integer> numeQue, Integer num) {
        while (!optQue1.isEmpty() && optQue1.peek() != '(') {
            char opt = optQue1.pop();
            int num2 = numeQue.pop();
            if (opt == '+') {
                num = num2 + num;
            } else {
                num = num2 - num;
            }
        }
        return num;
    }


    public static Integer calculate2(String s) {//废弃/不推荐
        s = s.replace(" ", "");
        if (s.startsWith("-")) {
            s = 0 + s;
        }
        String[] split = s.split("[+\\-*/]");//不适宜处理有负号的情况。
        System.out.println(Arrays.asList(split));
        Deque<Character> opQue1 = new ArrayDeque<>();
        Deque<String> numeQue = new ArrayDeque<>();
        if (s.startsWith("(")) {
            numeQue.push("0");
            opQue1.push('+');
        }
        int index = 0;
        for (int i = 0; i < split.length; i++) {
            numeQue.push(split[i]);
            while (!opQue1.isEmpty() && (numeQue.peek().endsWith(")") || !numeQue.peek().startsWith("("))) {
                String num2 = numeQue.pop();
                String num1 = numeQue.pop();
                String res = compute(num1, num2, opQue1.pop());
                if (res == null) {
                    return null;
                }
                numeQue.push(res);
            }
            index += split[i].length();
            if ((index + i) < s.length()) {
                opQue1.push(s.charAt(index + i));
            }


        }
        return Integer.parseInt(numeQue.pop());

    }


    public static String compute(String num1, String num2, char operator) {
        String a1 = num1.replace("(", "");
        String a2 = a1.replace(")", "");
        String b1 = num2.replace(")", "");
        String b2 = b1.replace("(", "");
        int tag = num1.length() + a2.length() - 2 * a1.length() - (num2.length() + b2.length() - 2 * b1.length());
        System.out.println(a2);
        int a = Integer.parseInt(0 + a2);
        int b = Integer.parseInt(b2);
        Integer res = null;
        switch (operator) {
            case '+':
                res = a + b;
                break;
            case '-':
                res = a - b;
                break;

            case '*':
                res = a * b;
                break;

            case '/':
                res = b == 0 ? null : a / b;
                break;

        }
        if (res == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        if (tag > 0) {
            for (int i = 0; i < tag; i++) {
                sb.append("(");
            }
            sb.append(res);
            return sb.toString();

        } else if (tag < 0) {
            sb.append(res);
            for (int i = 0; i < tag * -1; i++) {
                sb.append(")");
            }
            return sb.toString();
        }

        return sb.append(res).toString();
    }
}
